from http.server import SimpleHTTPRequestHandler, HTTPServer
import urllib
from urllib.parse import urlencode,urlparse, parse_qs, unquote
import os, string, sys, time, re, math, fileinput, glob, shutil
from string import Template
import chardet
import json
from aiohttp import web
from model.FileInf import FileInf
from datetime import datetime,timedelta
from PathBuilder import PathBuilder
import uuid
import SqlFile
from mmap import mmap, ACCESS_WRITE 
import base64
from FileBlockWriter import FileBlockWriter
from web import *

pathcur = sys.path[0] #示例：d:\\soft\\safe
routes = web.RouteTableDef()

#序列化时间
def datetime_converter(o):
    if isinstance(o, datetime):
        return o.strftime("%Y-%m-%d %H:%M:%S")
    raise TypeError(f"Type {type(o)} not serializable")

@routes.get('/api/up6/f_create')
async def up6_f_create(request):
    fileSvr = FileInf()
    fileSvr.id = request.query.get("id","")
    fileSvr.pid = request.query.get("pid","")
    fileSvr.pidRoot = request.query.get("pidRoot","")
    fileSvr.pathLoc = request.query.get("pathLoc","")
    # urldecode解码
    fileSvr.pathLoc = unquote(fileSvr.pathLoc.replace('+',' '))
    fileSvr.pathSvr = request.query.get("pathSvr","")
    fileSvr.pathRel = request.query.get("pathRel","")
    fileSvr.nameLoc = os.path.basename(fileSvr.pathLoc)
    fileSvr.nameSvr = fileSvr.nameLoc
    fileSvr.md5 = request.query.get("md5","")
    fileSvr.lenLoc = int(request.query.get("lenLoc","0"))
    fileSvr.sizeLoc = request.query.get("sizeLoc","0byte")
    fileSvr.pos = int(request.query.get("pos","0"))
    fileSvr.lenSvr = int(request.query.get("lenSvr","0"))
    fileSvr.perSvr = request.query.get("perSvr","")
    fileSvr.encryptAgo = request.query.get("encryptAgo","")
    fileSvr.blockSize = request.query.get("blockSize","0")
    fileSvr.blockSizeSec = int(request.query.get("blockSizeSec","0"))
    fileSvr.object_key = request.query.get("object_key","")    
    cbk = request.query.get("callback","")
    # 生成存储路径
    pb = PathBuilder()
    fileSvr.pathSvr = pb.mkFile(fileSvr.id,fileSvr.nameLoc)

    #添加到数据库
    fileExt = SqlFile.existMD5(fileSvr.md5)
    # 存在相同文件
    if fileExt:
        fileSvr.nameSvr = fileExt.nameSvr
        fileSvr.pathSvr = fileExt.pathSvr
        fileSvr.complete = fileExt.complete
        SqlFile.add(fileSvr)
    else:
        fbw = FileBlockWriter()
        fbw.make(fileSvr)
        SqlFile.add(fileSvr)
    
    #缩短路径
    fileSvr.pathSvr = pb.absToRel(fileSvr.pathSvr)

    #返回
    # res.text = json.dumps(fileSvr,ensure_ascii=False)
    str = json.dumps(fileSvr.__dict__,ensure_ascii=False)
    str = urlencode({"value":str})
    str = str.replace('+',"%20")
    str = str.replace("value=","")
    # 转成jsonp格式
    str = cbk+"({'value':'"+str+"','ret':true})"

    res = web.Response(content_type='application/json')
    res.text = str
    res.headers['Access-Control-Allow-Origin'] = "*"
    res.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
    res.headers['Access-Control-Allow-Headers'] = "Content-Type, Authorization"
    res.headers['Cache-Control'] = "no-store, no-cache, must-revalidate"
    return res

@routes.get('/api/up6/f_list')
async def up6_f_list(request):
    uid = request.query.get("uid","0")
    cbk = request.query.get("callback","")
    arr = SqlFile.uncmps()

    #返回
    str = json.dumps(arr,ensure_ascii=False)
    key = {"value":str}
    str = urlencode(key)
    str = str.replace('+',"%20")
    str = str.replace("value=","")
    res = web.Response(content_type='application/json')
    res.text = cbk + "({\"value\":\""+str+"\"})"
    res.headers['Access-Control-Allow-Origin'] = "*"
    res.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
    res.headers['Access-Control-Allow-Headers'] = "Content-Type, Authorization"
    res.headers['Cache-Control'] = "no-store, no-cache, must-revalidate"
    return res

@routes.get('/api/up6/f_del')
# 删除文件
async def up6_f_del(request):
    id = request.query.get("id","")
    uid = request.query.get("uid","0")
    cbk = request.query.get("callback","callback")

    SqlFile.delete(id,uid)

    #返回
    res = web.Response(content_type='application/json')
    res.text = json.dumps(data,ensure_ascii=False)
    #res.headers['Content-type'] = "text/html charset=utf-8"
    res.headers['Access-Control-Allow-Origin'] = "*"
    res.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
    res.headers['Access-Control-Allow-Headers'] = "Content-Type, Authorization"
    res.headers['Cache-Control'] = "no-store, no-cache, must-revalidate"
    return res

@routes.post('/api/up6/f_post')
# 上传文件块
async def up6_f_post(request):
    fileSvr = FileInf()
    fileSvr.id = request.headers.get("id","")
    fileSvr.uid = request.headers.get("uid","0")
    fileSvr.pid = request.headers.get("pid","")
    fileSvr.pidRoot = request.headers.get("pidRoot","")
    fileSvr.md5 = request.headers.get("md5","")
    fileSvr.lenLoc = int(request.headers.get("lenLoc","0"))
    fileSvr.sizeLoc = request.headers.get("sizeLoc","0byte")
    fileSvr.blockIndex = int(request.headers.get("blockIndex","0"))
    fileSvr.blockOffset = int(request.headers.get("blockOffset","0"))
    fileSvr.blockOffsetCry = int(request.headers.get("blockOffsetCry","0"))
    fileSvr.blockSize = int(request.headers.get("blockSize","0"))
    fileSvr.blockSizeSec = int(request.headers.get("blockSizeSec","0"))
    fileSvr.blockCount = int(request.headers.get("blockCount","0"))
    fileSvr.encryptAgo = request.headers.get("blockEncryptAgo","")

    form = FormReader()
    await form.read(request)

    fileSvr.pathLoc = form.fields["pathLoc"]
    fileSvr.pathSvr = form.fields["pathSvr"]
    fileSvr.pathRel = form.fields["pathRel"]
    fileSvr.pathLoc = base64.b64decode(fileSvr.pathLoc).decode("utf-8")
    fileSvr.pathSvr = base64.b64decode(fileSvr.pathSvr).decode("utf-8")
    fileSvr.pathRel = base64.b64decode(fileSvr.pathRel).decode("utf-8")
    fileSvr.nameLoc = os.path.basename(fileSvr.pathLoc)
    fileSvr.nameSvr = fileSvr.nameLoc
    print("解析前远程文件路径：")
    print(fileSvr.pathSvr)

    # 还原路径
    pb = PathBuilder()
    fileSvr.pathSvr = pb.relToAbs(fileSvr.pathSvr)
    print("远程文件路径：")
    print(fileSvr.pathSvr)

    # 写入文件
    fbw = FileBlockWriter()
    fbw.make(fileSvr)
    fbw.write(fileSvr,form.buffer)

    #返回
    res = web.Response(content_type='application/json')
    ret={"msg":"ok","offset":fileSvr.blockOffset}
    res.text = json.dumps(ret,ensure_ascii=False)
    res.headers['Access-Control-Allow-Origin'] = "*"
    res.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
    res.headers['Access-Control-Allow-Headers'] = "Content-Type, Authorization"
    res.headers['Cache-Control'] = "no-store, no-cache, must-revalidate"
    return res

@routes.get('/api/up6/f_process')
# 更新文件进度
async def up6_f_process(request):
    id = request.query.get("id","")
    uid = request.query.get("uid","0")
    offset = long(request.query.get("offset","0"))
    lenSvr = long(request.query.get("lenSvr","0"))
    perSvr = request.query.get("perSvr","0%")
    cbk = request.query.get("callback","callback")

    SqlFile.process(uid,id,offset,lenSvr,perSvr)

    #返回
    res = web.Response(content_type='application/json')
    res.text = f"{cbk}({'state':1})"
    res.headers['Access-Control-Allow-Origin'] = "*"
    res.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
    res.headers['Access-Control-Allow-Headers'] = "Content-Type, Authorization"
    res.headers['Cache-Control'] = "no-store, no-cache, must-revalidate"
    return res

@routes.get('/api/up6/f_complete')
# 更新文件状态，已经上传完成
async def up6_f_complete(request):
    id = request.query.get("id","")
    uid = request.query.get("uid","0")
    pid = request.query.get("pid","")
    md5 = request.query.get("md5","")
    cbk = request.query.get("callback","callback")

    SqlFile.complete(id)

    #返回
    res = web.Response(content_type='application/json')
    res.text = cbk+"(1)"
    #res.headers['Content-type'] = "text/html charset=utf-8"
    res.headers['Access-Control-Allow-Origin'] = "*"
    res.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
    res.headers['Access-Control-Allow-Headers'] = "Content-Type, Authorization"
    res.headers['Cache-Control'] = "no-store, no-cache, must-revalidate"
    return res

@routes.get('/api/up6/clear')
# 清除表记录
async def up6_clear(request):
    SqlFile.clear()

    #返回
    res = web.Response(text='ok')
    res.headers['Access-Control-Allow-Origin'] = "*"
    res.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
    res.headers['Access-Control-Allow-Headers'] = "Content-Type, Authorization"
    res.headers['Cache-Control'] = "no-store, no-cache, must-revalidate"
    return res

# 创建一个 aiohttp 应用实例，并添加路由
app = web.Application()
app.add_routes(routes)

# 运行服务器
if __name__ == '__main__':
    # print(ret["name"])
    # print(ret["key"])
    # print(ret["tmp"])
    # print(ret["tag"])
    web.run_app(app, host='127.0.0.1', port=11017)